package com.xyzq.hs;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

import com.xyzq.hs.util.ByteUtils;
import com.xyzq.hs.util.Logger;
import com.xyzq.hs.util.LoggerFactory;

public class TSClientImpl implements TSClient {
	Logger log=LoggerFactory.getLogger(TSClientImpl.class);
	private String host=null; 
	private Integer port=null; 
	private Integer timeout=10000;
	private Socket socket = null;
	private DataInputStream in = null;
	private DataOutputStream out = null;
	
	public TSClientImpl(String host, Integer port, Integer timeout) {
		super();
		this.host = host;
		this.port = port;
		this.timeout = timeout;
	}


	/* (non-Javadoc)
	 * @see com.xyzq.hs.ITSClient#doPost(com.xyzq.hs.Request)
	 */
	@Override
	public Response doPost(Request request){
		try {
			
			Response response=null;
			socket = new Socket(host, port);
			socket.setSoTimeout(timeout);
		    in = new DataInputStream(socket.getInputStream());
			out = new DataOutputStream(socket.getOutputStream());
			
			byte[] message = request.getMessage();
			
			if(log.isDebug()){
				ByteUtils.println("Request header ",ByteUtils.subBytes(message, 0, Header.HEADER_SIZE));
				ByteUtils.println("Request body   ",ByteUtils.subBytes(message, 20, message.length-Header.HEADER_SIZE));
			}

			out.write(message);
			byte[] headerByte=new byte[Header.HEADER_SIZE];
			in.read(headerByte);
			Header header=new Header(headerByte);
			if(log.isDebug()){
				ByteUtils.println("Response header",header.asBytes());
			}
			if(header.validate()){
				int bodySize = header.getBodySize();
				byte[] responseBody=new byte[bodySize];
				responseBody=read(in,bodySize);
				if(log.isDebug()){
					ByteUtils.println("Response body",responseBody);
				}
				response=new Response(responseBody);
			}else{
				log.error("Invalide response message.");
			}
			return response;
		} catch (Exception e) {
			throw new TSException(e);
		}finally{
			if(in!=null)
				try {
					in.close();
				} catch (IOException e) {
					throw new TSException(e);
				}
			if(out!=null)
				try {
					out.close();
				} catch (IOException e) {
					throw new TSException(e);
				}
			if(socket!=null){
				try {
					socket.close();
				} catch (IOException e) {
					throw new TSException(e);
				}
			}
			
		}
	}
	

	private byte[] read(InputStream in,int totalSize) throws IOException {
		byte[] buff = new byte[totalSize];
		int readCount = 0;
		while (readCount < totalSize) {
			readCount += in.read(buff, readCount, totalSize - readCount);
		}
		return buff;
	}
}
